home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
C/C++ Users Group Library 1996 July
/
C-C++ Users Group Library July 1996.iso
/
vol_100
/
148_01
/
a99asmln.c
< prev
next >
Wrap
Text File
|
1987-09-26
|
11KB
|
499 lines
/*
TMS9900/99105 Cross-Assembler v. 1.0
January, 1985
Original 6800 version Copyright (c) 1980 William C. Colley, III.
Modified for the TMS9900/99105 Series by Alexander Cameron.
File: a99asmln.c
Line assembly routine.
*/
/* Get globals: */
#include "a99.gbl"
/*
This function is the workhorse of the assembler. The routine
gets any labels off the line and processes them, gets the opcode
and builds the binary output as it evaluates the operand field.
*/
asmline()
{
char c,label[2*SYMLEN], opattr;
unsigned opcode,op2;
nbytes = 0;
address = pc;
directok = TRUE;
evalerr = FALSE;
hexflg = NOCODE;
label[0] = '\0';
binbuf[0] = binbuf[2] = binbuf[4] = 0x10;
binbuf[1] = binbuf[3] = binbuf[5] = 0; /* NOP = 0x1000 */
switch (getchr(&c,NOSKIP))
{
case ALPHA: backchr;
getname(label);
if (chkoprat(label) != NO_OPR)
{
markerr('L');
label[0] = '\0';
}
break;
case END_LIN: return;
case BLANK: break;
default: markerr('L');
while((c = getchr(&c,NOSKIP)) != BLANK && c != END_LIN);
backchr;
}
switch(getopcod(&opcode,&opattr))
{
case 0: nbytes = 0;
case -1: opcode = 255; /* Set nil pseudo-op. */
opattr = 0x80;
case 1: if ((opattr & (PSOP | IFGROUP)) == (PSOP | IFGROUP))
{
if (label[0] != '\0') markerr('L');
}
else
{
if (ifstack[ifsp] == 0) return;
if (label[0] != '\0')
{
strcat(label,PADDING);
if (pass == 1)
{
if (addsym(label))
{
sympoint -> symvalu = pc;
if ((opattr & PSOP) && opcode==0x000A)
{
sympoint -> symname[1] |= 0x80;
}
}
}
else
{
if (slookup(label))
{
markerr('P');
label[0] = '\0';
}
else
{
if (sympoint -> symvalu != pc || (sympoint -> symname[1] & 0x80))
{
markerr('M');
}
sympoint -> symname[0] &= 0x7f;
}
}
}
}
hexflg = PUTCODE;
if (opattr & PSOP) _psop(opcode,label);
else _normop(opcode,opattr);
return;
}
}
/*
Internal function to process pseudo opcodes.
*/
_psop(opcode,label)
char *label;
unsigned opcode;
{
char *bptr, c, d;
unsigned t,temp;
struct symbtbl *sptr;
sptr = sympoint;
bptr = binbuf;
switch (opcode)
{
case 0: t = eval(START); /* ORG. */
if (evalerr) return;
address = pc = t;
hexflg = FLUSH;
if (label[0] == '\0') goto chkargs;
backitem(t,VALUE);
backchr;
case 1: if (label[0] == '\0') /* EQU. */
{
markerr('L');
return;
}
if (!(sptr -> symname[1] & 0x80) && errcode == 'M')
{
errcode = ' ';
errcount--;
}
t = eval(START);
if (evalerr) return;
address = sptr -> symvalu;
sptr -> symvalu = t;
if (!directok) markerr('P');
if (address != t) markerr('M');
goto chkargs;
case 2: /* BYTE */
while ((c = getitem(&t,SMALST)) != END_LIN)
{
if (c == COMMA)
{
*bptr++ = 0;
nbytes++;
continue;
}
backitem(t,c);
t = eval(START);
/* mod because eval now returns delimeter- gobbles up comma */
c=getitem(&temp,SMALST);
if (evalerr || t > 0xff && t < 0xff80) markerr('V');
*bptr++ = t;
nbytes++;
if(c==END_LIN) return;
}
return;
case 3: /* WORD */
while ((c = getitem(&t,SMALST)) != END_LIN)
{
if (c == COMMA)
{
*bptr++ = 0;
*bptr++ = 0;
nbytes += 2;
continue;
}
backitem(t,c);
t=eval(START);
c=getitem(&temp,SMALST);
*bptr++ = t >> 8;
*bptr++ = t;
nbytes += 2;
if(c==END_LIN) return;
}
return;
case 4: /* TEXT */
while ((c = getchr(&d,SKIP)) != END_LIN)
{
if (c == COMMA) continue;
if (c != QUOTE)
{
markerr('"');
/*return;*/
}
while ((c = *linptr++) != d)
{
if (c == '\n')
{
markerr('"');
return;
}
*bptr++ = c;
nbytes++;
}
}
return;
case 5: t = eval(START); /* BSS */
/* if (evalerr) return; */
pc += t;
hexflg = FLUSH;
goto chkargs;
case 6: if (pass == 1) pass--; /* END. */
else
{
pass++;
if (ifsp != 0) markerr('I');
}
hexflg = NOMORE;
goto chkargs;
case 7: /* ELSE. */
case 8: hexflg = NOCODE; /* ENDI. */
if (ifsp == 0)
{
markerr('I');
return;
}
if (opcode == 8) ifsp--;
else ifstack[ifsp] = ~ifstack[ifsp];
goto chkargs;
case 9: t = eval(START); /* IF. */
if (evalerr || !directok)
{
markerr('P');
t = 0xffff;
}
if (ifsp == 16) wipeout("\nIf stack overflow.\n");
ifstack[++ifsp] = address = t;
goto chkargs;
case 10: if (label[0] == '\0') /* SET. */
{
markerr('L');
return;
}
if ((sptr -> symname[1] & 0x80) && errcode == 'M')
{
errcode = ' ';
errcount--;
}
t = eval(START);
if (evalerr) return;
address = sptr -> symvalu = t;
if (!directok) markerr('P');
goto chkargs;
case 11: if(pc & 1) /* EVEN */
{ nbytes++;
*bptr=0;
}
goto chkargs;
case 12: hexflg=NOCODE; /* DXOP */
if(getchr(&c,SKIP) != ALPHA)
{
markerr('S');
return;
}
backchr;
getname(label); /* name of DXOP */
strcat(label,PADDING);
getitem(&t,SMALST); /* skip to number */
t=eval(START); /* DXOP number */
if(evalerr || t >15)
{
markerr('S');
return;
}
if( pass == 1)
if(addsym(label)) sympoint ->symvalu = ( 0x2C00 | t << 6 ); /* XOP opcode */
return;
chkargs: if (getitem(&c,SMALST) != END_LIN) markerr('T');
return;
case 255: /* NO OPCODE. */
if (nbytes == 0) hexflg = NOCODE;
return;
}
}
/*
Internal function to process normal (non-pseudo) opcodes.
*/
_normop(opcode,attr)
unsigned opcode;
char attr;
{
unsigned regmask,regval,t,operand,value;
int disp;
char shift,c,parse,opdcount,attr1,attr2;
nbytes = 2;
if(pc & 1){ pc++; address++; } /* make sure code is on an even boundary */
operand=0;
attr1=attr & 0x07; /* mask 3 most least significant bits */
attr2=(attr & 0x38) >> 3; /* next 3 bits represent attr2 */
attr=attr1;
opdcount=1;
while(TRUE)
{ parse=TRUE;
addrmode=WREG; /* default address mode */
switch(attr)
{
case 0: if(attr1 || attr2) markerr('S');
binbuf[0] = opcode >> 8;
binbuf[1] = opcode;
if(c=getitem(&value,SMALST) != END_LIN) markerr('T');
return;
/* Format 1 - S,D */
/* detect N,*N,*N+,@X,@X(N) */
case 1: while(parse)
{
switch(c=getitem(&value,SMALST))
{
case OPERATR: if(value=='*')addrmode=INDIRECT;
if(value=='@')
{
addrmode=SYMBOLIC;
nbytes += 2;
}
break;
case VALUE : regval = 0;
backitem(value,c);
t=eval(START);
if(evalerr) markerr('S');
switch(addrmode)
{
case WREG: regval=t;regmask=0;break;
case INDIRECT: regval=t;regmask=1;break;
case AUTOINC: regval=t;regmask=3;break;
case SYMBOLIC: regmask=2;
binbuf[nbytes - 2] = t>>8;
binbuf[nbytes - 1] = t;
break;
case INDEXED: regmask=2;
binbuf[nbytes - 2] = t >> 8;
binbuf[nbytes - 1] = t;
regval=eval(START);
if(evalerr) markerr('E');
}
if(regval > 15) markerr('R');
if(opdcount == 2) shift=6;
else shift=0;
operand |= (regval << shift);
operand |= (regmask << shift + 4);
break;
case COMMA: opdcount++;
if(opdcount > 3) {markerr('T'); break;}
attr=attr2;
parse=FALSE;
break;
case END_LIN: opcode |= operand;
binbuf[0